package com.school.sports.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.school.sports.dto.ProjectDTO;
import com.school.sports.entity.Project;
import com.school.sports.entity.User;
import com.school.sports.service.ProjectService;
import com.school.sports.common.Result;
import lombok.extern.slf4j.Slf4j;
import javax.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

/**
 * 运动项目管理控制器
 * 提供运动项目的增删改查、状态管理等功能
 */
@Slf4j
@RestController
@RequestMapping("/api/projects")
public class ProjectController {

    @Autowired
    private ProjectService projectService;

    /**
     * 分页查询项目列表
     * @param currentPage 当前页码
     * @param pageSize 每页大小
     * @param name 项目名称
     * @param type 项目类型
     * @param status 项目状态
     * @param genderLimit 性别限制
     * @return 分页结果
     */
    @GetMapping("/page/{currentPage}/{pageSize}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<IPage<Project>> getProjectPage(
            @PathVariable("currentPage") Integer currentPage,
            @PathVariable("pageSize") Integer pageSize,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "type", required = false) String type,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "genderLimit", required = false) String genderLimit) {

        log.info("分页查询项目列表，当前页码：{}，每页条数：{}，查询条件：name={}, type={}, status={}, genderLimit={}",
                currentPage, pageSize, name, type, status, genderLimit);

        try {
            Page<Project> page = new Page<>(currentPage, pageSize);
            LambdaQueryWrapper<Project> queryWrapper = new LambdaQueryWrapper<>();

            // 构建查询条件
            queryWrapper.eq(Project::getDeleted, 0)
                    .like(StringUtils.hasText(name), Project::getName, name)
                    .eq(StringUtils.hasText(type), Project::getType, type)
                    .eq(StringUtils.hasText(status), Project::getStatus, status)
                    .eq(StringUtils.hasText(genderLimit), Project::getGenderLimit, genderLimit)
                    .orderByDesc(Project::getCreatedAt);

            IPage<Project> projectPage = projectService.page(page, queryWrapper);
            log.info("查询项目列表成功，共{}条记录", projectPage.getTotal());
            return Result.success(projectPage);
        } catch (Exception e) {
            log.error("查询项目列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 分页查询项目信息（包含创建者和统计信息）
     * 使用优化的JOIN查询避免N+1问题
     *
     * @param currentPage 当前页码
     * @param pageSize 每页大小
     * @param name 项目名称（可选）
     * @param type 项目类型（可选）
     * @param status 项目状态（可选）
     * @param genderLimit 性别限制（可选）
     * @return 分页结果
     */
    @GetMapping("/page-with-details/{currentPage}/{pageSize}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<IPage<ProjectDTO>> getProjectPageWithDetails(
            @PathVariable("currentPage") Integer currentPage,
            @PathVariable("pageSize") Integer pageSize,
            @RequestParam(value = "name", required = false) String name,
            @RequestParam(value = "type", required = false) String type,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "genderLimit", required = false) String genderLimit) {

        log.info("分页查询项目信息（包含详细信息），当前页码：{}，每页条数：{}，查询条件：name={}, type={}, status={}, genderLimit={}",
                currentPage, pageSize, name, type, status, genderLimit);

        // 参数校验
        if (currentPage == null || currentPage <= 0) {
            currentPage = 1;
        }
        if (pageSize == null || pageSize <= 0 || pageSize > 100) {
            pageSize = 10;
        }

        try {
            Page<ProjectDTO> page = new Page<>(currentPage, pageSize);
            IPage<ProjectDTO> result = projectService.getProjectPageWithDetails(page, name, type, status, genderLimit);
            log.info("查询项目信息（包含详细信息）成功，共{}条记录", result.getTotal());
            return Result.success(result);
        } catch (Exception e) {
            log.error("查询项目信息（包含详细信息）异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据项目ID查询项目详细信息（包含创建者和报名统计）
     *
     * @param projectId 项目ID
     * @return 项目详细信息
     */
    @GetMapping("/{projectId}/details")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<ProjectDTO> getProjectDetailsById(@PathVariable("projectId") Long projectId) {
        log.info("查询项目详细信息，项目ID：{}", projectId);

        if (projectId == null || projectId <= 0) {
            return Result.fail("项目ID无效");
        }

        try {
            ProjectDTO project = projectService.getProjectDetailsById(projectId);
            if (project == null) {
                return Result.fail("项目不存在");
            }
            log.info("查询项目详细信息成功，项目名称：{}", project.getName());
            return Result.success(project);
        } catch (Exception e) {
            log.error("查询项目详细信息异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据项目名称模糊查询项目（包含详细信息）
     * 使用优化的索引查询
     *
     * @param name 项目名称
     * @param currentPage 当前页码
     * @param pageSize 每页大小
     * @return 分页结果
     */
    @GetMapping("/search-by-name")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<List<ProjectDTO>> searchProjectsByName(
            @RequestParam("name") String name,
            @RequestParam(value = "currentPage", defaultValue = "1") Integer currentPage,
            @RequestParam(value = "pageSize", defaultValue = "20") Integer pageSize) {

        log.info("根据项目名称搜索项目，名称：{}，当前页码：{}，每页条数：{}", name, currentPage, pageSize);

        if (name == null || name.trim().isEmpty()) {
            return Result.fail("项目名称不能为空");
        }

        // 参数校验
        if (currentPage == null || currentPage <= 0) {
            currentPage = 1;
        }
        if (pageSize == null || pageSize <= 0 || pageSize > 50) {
            pageSize = 20;
        }

        try {
            List<ProjectDTO> projects = projectService.searchProjectsByName(name.trim());
            log.info("根据项目名称搜索项目成功，共{}条记录", projects.size());
            return Result.success(projects);
        } catch (Exception e) {
            log.error("根据项目名称搜索项目异常：{}", e.getMessage(), e);
            return Result.fail("搜索失败：" + e.getMessage());
        }
    }

    /**
     * 查询可报名的项目列表
     *
     * @return 可报名项目列表
     */
    @GetMapping("/available")
    @PreAuthorize("hasAnyRole('管理员', '老师', '学生')")
    public Result<List<ProjectDTO>> getAvailableProjects() {
        log.info("查询可报名的项目列表");

        try {
            List<ProjectDTO> projects = projectService.getAvailableProjects();
            log.info("查询可报名项目列表成功，共{}个", projects.size());
            return Result.success(projects);
        } catch (Exception e) {
            log.error("查询可报名项目列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询项目详情
     * @param projectId 项目ID
     * @return 项目详情
     */
    @GetMapping("/{projectId}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<Project> getProjectById(@PathVariable("projectId") Long projectId) {
        log.info("查询项目详情，项目ID：{}", projectId);

        if (projectId == null || projectId <= 0) {
            return Result.fail("项目ID无效");
        }

        try {
            Project project = projectService.getProjectWithCreator(projectId);
            if (project == null) {
                return Result.fail("项目不存在");
            }
            log.info("查询项目详情成功，项目名称：{}", project.getName());
            return Result.success(project);
        } catch (Exception e) {
            log.error("查询项目详情异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 新增项目
     * @param project 项目信息
     * @return 操作结果
     */
    @PostMapping
    @PreAuthorize("hasRole('管理员')")
    public Result<String> addProject(@Valid @RequestBody Project project) {
        log.info("新增项目：{}", project.getName());

        try {
            // 参数校验
            if (project.getName() == null || project.getName().trim().isEmpty()) {
                return Result.fail("项目名称不能为空");
            }

            if (project.getType() == null || project.getType().trim().isEmpty()) {
                return Result.fail("项目类型不能为空");
            }

            // 校验项目名称是否已存在
            if (projectService.existsByName(project.getName())) {
                return Result.fail("新增失败，项目名称已存在");
            }

            // 设置创建人和创建时间
            User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            project.setCreatedBy(currentUser.getId());
            project.setCreatedAt(LocalDateTime.now());
            project.setUpdatedAt(LocalDateTime.now());
            project.setDeleted(0);

            // 设置默认状态
            if (project.getStatus() == null || project.getStatus().trim().isEmpty()) {
                project.setStatus("未开始");
            }

            // 设置默认性别限制
            if (project.getGenderLimit() == null || project.getGenderLimit().trim().isEmpty()) {
                project.setGenderLimit("无");
            }

            // 设置默认轮次
            if (project.getRounds() == null) {
                project.setRounds(1);
            }

            boolean success = projectService.save(project);
            if (success) {
                log.info("新增项目成功：{}", project.getName());
                return Result.success("添加成功");
            } else {
                return Result.fail("添加失败");
            }
        } catch (Exception e) {
            log.error("新增项目异常：{}", e.getMessage(), e);
            return Result.fail("添加失败：" + e.getMessage());
        }
    }

    /**
     * 更新项目信息
     * @param project 项目信息
     * @return 操作结果
     */
    @PutMapping
    @PreAuthorize("hasRole('管理员')")
    public Result<String> updateProject(@Valid @RequestBody Project project) {
        log.info("更新项目信息：{}", project.getId());

        if (project.getId() == null || project.getId() <= 0) {
            return Result.fail("项目ID无效");
        }

        try {
            // 检查项目是否存在
            Project existingProject = projectService.getById(project.getId());
            if (existingProject == null) {
                return Result.fail("项目不存在");
            }

            // 如果修改了项目名称，检查新名称是否已存在
            if (!existingProject.getName().equals(project.getName()) &&
                projectService.existsByName(project.getName())) {
                return Result.fail("项目名称已存在");
            }

            // 设置更新时间
            project.setUpdatedAt(LocalDateTime.now());
            // 保持原有的创建信息和创建人
            project.setCreatedAt(existingProject.getCreatedAt());
            project.setCreatedBy(existingProject.getCreatedBy());
            project.setDeleted(0);

            boolean success = projectService.updateById(project);
            if (success) {
                log.info("更新项目信息成功：{}", project.getId());
                return Result.success("更新成功");
            } else {
                return Result.fail("更新失败");
            }
        } catch (Exception e) {
            log.error("更新项目信息异常：{}", e.getMessage(), e);
            return Result.fail("更新失败：" + e.getMessage());
        }
    }

    /**
     * 删除项目
     * @param projectId 项目ID
     * @return 操作结果
     */
    @DeleteMapping("/{projectId}")
    @PreAuthorize("hasRole('管理员')")
    public Result<String> deleteProject(@PathVariable("projectId") Long projectId) {
        log.info("删除项目：{}", projectId);

        if (projectId == null || projectId <= 0) {
            return Result.fail("项目ID无效");
        }

        try {
            Project project = projectService.getById(projectId);
            if (project == null) {
                return Result.fail("项目不存在");
            }

            // 检查项目状态，已开始的项目不能删除
            if ("进行中".equals(project.getStatus()) || "已结束".equals(project.getStatus())) {
                return Result.fail("项目已开始或已结束，不能删除");
            }

            // 逻辑删除
            project.setDeleted(1);
            project.setUpdatedAt(LocalDateTime.now());
            boolean success = projectService.updateById(project);

            if (success) {
                log.info("删除项目成功：{}", projectId);
                return Result.success("删除成功");
            } else {
                return Result.fail("删除失败");
            }
        } catch (Exception e) {
            log.error("删除项目异常：{}", e.getMessage(), e);
            return Result.fail("删除失败：" + e.getMessage());
        }
    }

    /**
     * 批量删除项目
     * @param projectIds 项目ID列表
     * @return 操作结果
     */
    @DeleteMapping("/batch")
    @PreAuthorize("hasRole('管理员')")
    public Result<String> batchDeleteProjects(@RequestBody List<Long> projectIds) {
        log.info("批量删除项目：{}", projectIds);

        if (projectIds == null || projectIds.isEmpty()) {
            return Result.fail("请选择要删除的项目");
        }

        try {
            int failedCount = 0;
            for (Long projectId : projectIds) {
                Project project = projectService.getById(projectId);
                if (project == null) {
                    failedCount++;
                    continue;
                }

                // 检查项目状态
                if ("进行中".equals(project.getStatus()) || "已结束".equals(project.getStatus())) {
                    failedCount++;
                    continue;
                }

                // 逻辑删除
                project.setDeleted(1);
                project.setUpdatedAt(LocalDateTime.now());
                if (!projectService.updateById(project)) {
                    failedCount++;
                }
            }

            if (failedCount == 0) {
                log.info("批量删除项目成功，共{}个项目", projectIds.size());
                return Result.success("批量删除成功");
            } else {
                log.warn("批量删除部分失败，失败{}个", failedCount);
                return Result.fail("批量删除部分失败");
            }
        } catch (Exception e) {
            log.error("批量删除项目异常：{}", e.getMessage(), e);
            return Result.fail("批量删除失败：" + e.getMessage());
        }
    }

    /**
     * 更改项目状态
     * @param projectId 项目ID
     * @param status 新状态
     * @return 操作结果
     */
    @PutMapping("/{projectId}/status")
    @PreAuthorize("hasRole('管理员')")
    public Result<String> updateProjectStatus(
            @PathVariable("projectId") Long projectId,
            @RequestParam("status") String status) {

        log.info("修改项目状态：{} -> {}", projectId, status);

        if (projectId == null || projectId <= 0) {
            return Result.fail("项目ID无效");
        }

        if (!isValidStatus(status)) {
            return Result.fail("状态不合法");
        }

        try {
            boolean success = projectService.updateProjectStatus(projectId, status);
            if (success) {
                log.info("修改项目状态成功：{}", projectId);
                return Result.success("状态修改成功");
            } else {
                return Result.fail("状态修改失败，项目不存在或状态流转不合法");
            }
        } catch (Exception e) {
            log.error("修改项目状态异常：{}", e.getMessage(), e);
            return Result.fail("状态修改失败：" + e.getMessage());
        }
    }

    /**
     * 获取项目类型列表
     * @return 项目类型列表
     */
    @GetMapping("/types")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<String>> getProjectTypes() {
        log.info("获取项目类型列表");
        try {
            List<String> types = Arrays.asList("径赛", "田赛", "球类", "其他");
            log.info("获取项目类型列表成功，共{}种类型", types.size());
            return Result.success(types);
        } catch (Exception e) {
            log.error("获取项目类型列表异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 获取项目状态列表
     * @return 项目状态列表
     */
    @GetMapping("/statuses")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<String>> getProjectStatuses() {
        log.info("获取项目状态列表");
        try {
            List<String> statuses = Arrays.asList("未开始", "报名中", "进行中", "已结束", "已取消");
            log.info("获取项目状态列表成功，共{}种状态", statuses.size());
            return Result.success(statuses);
        } catch (Exception e) {
            log.error("获取项目状态列表异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 获取性别限制列表
     * @return 性别限制列表
     */
    @GetMapping("/gender-limits")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<String>> getGenderLimits() {
        log.info("获取性别限制列表");
        try {
            List<String> limits = Arrays.asList("男", "女", "无");
            log.info("获取性别限制列表成功，共{}种限制", limits.size());
            return Result.success(limits);
        } catch (Exception e) {
            log.error("获取性别限制列表异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 校验状态合法性
     */
    private boolean isValidStatus(String status) {
        return "未开始".equals(status) || "报名中".equals(status)
                || "进行中".equals(status) || "已结束".equals(status)
                || "已取消".equals(status);
    }
}